今天來綜合一下前面寫的測試吧,利用useFetchUsers()
拿到的資料更新 component ,再判斷顯示是否正確。
我們稍微改寫一下 useFetchUsers()
,讓他多回傳 loading 這個 state。
import axios from 'axios';
import { useState, useEffect } from 'react';
interface User {
id: string;
username: string;
}
function useFetchUsers() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const fetchUsers = async () => {
try {
const result = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
setUsers(result.data);
setLoading(false);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
fetchUsers();
}, []);
return {users, loading};
}
export default useFetchUsers;
那我們建立一個 component 去顯示拿到的資料
import useFetchUsers from "../../utils/hooks/useFetchUsers";
const UserList = () => {
const { users, loading } = useFetchUsers();
return (
<>
<h1>Users</h1>
{
loading ?
<p>loading...</p> :
<>
{users.map((user: any) => (
<p key={user.id}>{user.username}</p>
))}
</>
}
</>
);
}
export default UserList;
這個 component 需要測試的有
import UserList from ".";
import { render, screen } from "@testing-library/react";
import '@testing-library/jest-dom';
import axios from "axios";
describe("UserList", () => {
it("拿到users data 前 render loading", async () => {
render(<UserList />);
expect(screen.getByText("loading...")).toBeInTheDocument();
});
it("拿到users data 後 render users", async () => {
const mockAxios = jest.spyOn(axios, 'get');
mockAxios.mockResolvedValueOnce({
data: [
{ id: '1', username: 'Dylan' },
{ id: '2', username: 'Chloe' },
{ id: '3', username: 'John' },
],
});
render(<UserList />);
expect(await screen.findByText("Dylan")).toBeInTheDocument();
});
});
在一進入畫面時 api 尚未回覆資料,所以第一個 loading 的測試不用去等待,利用 getByText
來看 loading 的文字是否存在。
測試有資料時,由於在 useFetchUsers()
中有使用到 axios.get
,為了不讓測試受到網路狀態的影響,我們這邊要去模擬 axios
,最後使用 Day11 中提到的 findBy
去找的我們模擬的資料,就完成這個 component 的測試了。
這邊提醒一下,如果是有用到 <li>
的話,那就不要去使用 ByText
我之前不知道這件事測到往生,<li>
的話可以使用 ByRole
跟 length 去判斷 listItem數量是否正確。
如果有什麼錯誤的地方,再請各位大神指正